package com.netrust.cmsx.admin.modules.sys.utils;

import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;

import com.netrust.cmsx.admin.modules.sys.common.AStatic;
import com.netrust.cmsx.admin.modules.sys.pojo.MenuPo;
import com.netrust.cmsx.admin.modules.sys.security.Principal;
import com.netrust.cmsx.admin.modules.sys.service.MenuService;
import com.netrust.cmsx.admin.modules.sys.service.RoleService;
import com.netrust.cmsx.admin.modules.sys.service.UserService;
import com.netrust.cmsx.entity.module.sys.Menu;
import com.netrust.cmsx.entity.module.sys.Role;
import com.netrust.cmsx.entity.module.sys.User;
import com.netrust.cmsx.utils.SpringContextHolder;
import com.netrust.cmsx.utils.collections.CollectionUtils;

public class UserUtils {
	private static MenuService menuService = SpringContextHolder.getBean(MenuService.class);
	private static UserService userService = SpringContextHolder.getBean(UserService.class);
	private static RoleService roleService = SpringContextHolder.getBean(RoleService.class);
	
	/**
	 * 获取当前用户
	 * @return 取不到返回 new User()
	 */
	public static User getUser(){
		Principal principal = UserUtils.getPrincipal();
		if (principal!=null){
			User user = userService.get(principal.getId());
			if (user != null){
				return user;
			}
			return new User();
		}
		// 如果没有登录，则返回实例化空的User对象。
		return new User();
	}
	
	/**
	 * 根据ID获取用户
	 * @param id
	 * @return 取不到返回null
	 */
	public static User getUser(String id){
		User user = (User)CacheUtils.get(AStatic.Cache.USER_CACHE, AStatic.Cache.USER_CACHE_ID_ + id);
		if (user ==  null){
			user = userService.get(id);
			if (user == null){
				return null;
			}
			CacheUtils.put(AStatic.Cache.USER_CACHE, AStatic.Cache.USER_CACHE_ID_ + user.getId(), user);
			CacheUtils.put(AStatic.Cache.USER_CACHE, AStatic.Cache.USER_CACHE_LOGIN_NAME_ + user.getLoginName(), user);
		}
		return user;
	}
	
	/**
	 * 根据登录名获取用户
	 * @param loginName
	 * @return 取不到返回null
	 */
	public static User getUserByLoginName(String loginName){
		User user = (User)CacheUtils.get(AStatic.Cache.USER_CACHE, AStatic.Cache.USER_CACHE_LOGIN_NAME_ + loginName);
		if (user == null){
			user = userService.getByLoginName(loginName);
			if (user == null){
				return null;
			}
			CacheUtils.put(AStatic.Cache.USER_CACHE, AStatic.Cache.USER_CACHE_ID_ + user.getId(), user);
			CacheUtils.put(AStatic.Cache.USER_CACHE, AStatic.Cache.USER_CACHE_LOGIN_NAME_ + user.getLoginName(), user);
		}
		return user;
	}
	
	/**
	 * 获取当前用户的授权菜单
	 * @return
	 */
	public static  List<Menu> findMenu4CurrentUser(){
		@SuppressWarnings("unchecked")
		List<Menu> menuList = (List<Menu>)UserUtils.getCache(AStatic.Cache.CACHE_User_Menu_List);
		if (menuList == null){
			User user = getUser();
			user.setId("1");//测试使用
			menuList=menuService.findByUserId(user.getId(),AStatic.mtype_menu);
			putCache(AStatic.Cache.CACHE_User_Menu_List, menuList);
		};
		return menuList;
	}
	
	/**
	 * 查询当前用户拥有的角色
	 * @return
	 */
	public static  List<Role> findRoles4CurrentUser(){
		@SuppressWarnings("unchecked")
		List<Role> roleList = (List<Role>)getCache(AStatic.Cache.CACHE_ROLE_LIST);
		if (roleList == null){
			roleList = roleService.findRole4CurrentUser();
			putCache(AStatic.Cache.CACHE_ROLE_LIST, roleList);
		}
		
		return roleList;
	}

	/**
	 * 获取当前用户的授权菜单树
	 * @return
	 */
	public static List<MenuPo> findMenuTree4CurrentUser(){
		@SuppressWarnings("unchecked")
		List<MenuPo> menuPoList = (List<MenuPo>)getCache(AStatic.Cache.CACHE_User_Menu_Tree);
		if (menuPoList == null){
			List<Menu> menuList=findMenu4CurrentUser();
			menuPoList=menuService.findTreeMenuPoFromMenu(menuList);
			putCache(AStatic.Cache.CACHE_User_Menu_Tree, menuPoList);
		};
		return menuPoList;
	}
	
	
	/**
	 * 获取当前用户授权资源列表
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static List<String> findPermissions4CurrentUser(){
		List<String> permissionList = (List<String>)getCache(AStatic.Cache.cache_permission_List);
		if (permissionList == null){
			User user = getUser();
			if(user.getId()!=null){
				return permissionList;
			}
			
			List<Menu> menuList=menuService.findByUserId(getUser().getId(),AStatic.mtype_permission);
			permissionList=CollectionUtils.extractToList(menuList,AStatic.mtype_permission);
			putCache(AStatic.Cache.cache_permission_List, permissionList);
		};
		return permissionList;
	}
	
	/**
	 * 获取当前登录者对象
	 */
	public static Principal getPrincipal(){
		try{
			Subject subject = SecurityUtils.getSubject();
			Principal principal = (Principal)subject.getPrincipal();
			if (principal != null){
				return principal;
			}
		}catch (UnavailableSecurityManagerException e) {
			e.printStackTrace();
		}catch (InvalidSessionException e){
			e.printStackTrace();
		}
		return null;
	}
	


	
	public static Session getSession(){
		try{
			Subject subject = SecurityUtils.getSubject();
			Session session = subject.getSession(false);
			if (session == null){
				session = subject.getSession();
			}
			if (session != null){
				return session;
			}
		}catch (InvalidSessionException e){
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 清除当前用户缓存
	 * @param user
	 */
	public static void clearCache(){
		removeCache( AStatic.Cache.CACHE_AUTH_INFO);
		removeCache( AStatic.Cache.CACHE_ROLE_LIST);
		removeCache( AStatic.Cache.CACHE_User_Menu_List);
		removeCache( AStatic.Cache.CACHE_User_Menu_Tree);
		removeCache( AStatic.Cache.cache_permission_List);
		UserUtils.clearCache(getUser());
	}
	/**
	 * 清除指定用户缓存
	 * @param user
	 */
	public static void clearCache(User user){
		CacheUtils.remove(AStatic.Cache.USER_CACHE, AStatic.Cache.USER_CACHE_ID_ + user.getId());
		CacheUtils.remove(AStatic.Cache.USER_CACHE, AStatic.Cache.USER_CACHE_LOGIN_NAME_ + user.getLoginName());
		CacheUtils.remove(AStatic.Cache.USER_CACHE, AStatic.Cache.USER_CACHE_LOGIN_NAME_ + user.getOldLoginName());
	}
	
	
	
	// ============== User Cache ==============
	public static Object getCache(String key) {
		return getCache(key, null);
	}
	
	public static Object getCache(String key, Object defaultValue) {
		Object obj = getSession().getAttribute(key);
		return obj==null?defaultValue:obj;
	}

	public static void putCache(String key, Object value) {
		getSession().setAttribute(key, value);
	}

	public static void removeCache(String key) {
		getSession().removeAttribute(key);
	}
}
